#include "Common.h"

void Session::HandleMovement(RealmPacket& data)
{
	m_movehandler->PullMovementInfo(&data);
	if(data.GetOpcode() == MSG_MOVE_FALL_LAND)
	{
		float old_pos;
		if(m_movehandler->last_z)
			old_pos = m_movehandler->last_z;
		else
			old_pos = m_player->GetPosition()._z;
		double delta = fabs(old_pos - m_movehandler->z);
		if(delta > 12)
		{
			float prct = ((float)m_player->GetUI32Value(UNIT_FIELD_MAXHEALTH) * 1.7f) / 100.0f;
			ui32 dmg = ui32((delta - 12) * prct);
			dmg = min(dmg, m_player->GetUI32Value(UNIT_FIELD_HEALTH) - 1);
			i32 new_health = m_player->GetUI32Value(UNIT_FIELD_HEALTH) - dmg;
			if(new_health <= 0)
				new_health = 1;
			m_player->SetUI32Value(UNIT_FIELD_HEALTH, new_health);
			m_player->LogEnvironmentalDamage(dmg, 2);
		}
	}
	m_player->SetPosition(m_movehandler->x, m_movehandler->y, m_movehandler->z, m_movehandler->o);
	if(!m_movehandler->fallen && !m_movehandler->jumped)
		m_movehandler->last_z = m_movehandler->z;

	if(sWorld.checkareaonmove)
	{
		ui16 area = m_player->GetMapHandler()->GetAreaId(m_movehandler->x, m_movehandler->y);
		if(area != NO_AREA_RESULT && area != m_player->GetAreaId())
		{
			sHookMgr->OnAreaChanged(area, m_player);
			m_player->m_areaid = area;
		}
	}

	m_player->m_moved = true;
	m_player->GetMapHandler()->UpdateMapCell(m_player);
	if(m_player->GetMapHandler())
		m_player->GetMapHandler()->AddUpdateObject(m_player);
	if(!m_player->m_inrangeset.size())
		return;
	RealmPacket data2(data.GetOpcode(), 0);
	data2 << m_moverguid;
	ui16 pos = data2.GetSize();
	data2.Append(data.Contents(), data.GetSize());
	*(ui32*)&data2.Contents()[pos + 6] = 500 + timeGetTime();
	SendToSet(&data2);
}

void MovementHandler::PullMovementInfo(RealmPacket* pack)
{
	Reset();
	jumped = fallen = swimming = flying = taxi = false;
	RealmPacket movepacket(pack->GetOpcode(), 0);
	movepacket.Resize(pack->GetSize());
	memcpy(movepacket.Contents(), pack->Contents(), pack->GetSize());
	movepacket >> unk_320 >> lastflags >> _230 >> time >> x >> y >> z >> o;
	if(lastflags & MOVEFLAG_TAXI)
	{
		taxi = true;
		movepacket >> transporter >> Tx >> Ty >> Tz >> To >> Tu >> Tu2;
	}

	if(lastflags & (MOVEFLAG_AIR_SWIMMING | MOVEFLAG_AIR_SWIMMING) ||  _230 & 0x20)
	{
		movepacket >> pitch;
	}

	movepacket >> unklast;

	if(lastflags & MOVEFLAG_FALLING || lastflags & MOVEFLAG_JUMPING)
	{
		movepacket >> falltime >> unk1 >> unk2 >> unk3;
		if(lastflags & MOVEFLAG_FALLING)
			fallen = true;
		if(lastflags & MOVEFLAG_JUMPING)
			jumped = true;
	}

	if(lastflags & MOVEFLAG_SPLINE_MOVER)
		movepacket >> splineunk;
}